global !p
from conversions import *
endglobal

snippet enuma "Anonymous enumeration" !b
enum
{
  ${1:ITEM},
};$0
endsnippet

snippet class "Class declaration" !b
class ${1:`!p snip.rv = snakecase_to_camelcase(snip.basename) or "Name"`}
{

public:

  ${1/(\w+).*/$1/}(${2});

  virtual ~${1/(\w+).*/$1/}() { };

private:

  $0

};
endsnippet

snippet ns "Namespace" !b
namespace ${1}
{

$0

}
endsnippet

snippet up "Unique pointer"
std::unique_ptr<${1:${VISUAL:Type}}>$0
endsnippet

snippet sp "Shared pointer"
std::shared_ptr<${1:${VISUAL:Type}}>$0
endsnippet

snippet tdup "Typedef unique pointer" !b
typedef std::unique_ptr<${1:Type}> ${2:UPtr};$0
endsnippet

snippet tdsp "Typedef shared pointer" !b
typedef std::shared_ptr<${1:Type}> ${2:Ptr};$0
endsnippet

snippet sc "Static cast"
static_cast<${2:int}>(${1:${VISUAL:variable}})$0
endsnippet

snippet rc "Reinterpret cast"
reinterpret_cast<${2:float*}>(${1:${VISUAL:variable}})$0
endsnippet

snippet temp "Template" !b
template <typename ${1:T}>$0
endsnippet

snippet tn "Typename" !b
typename $0
endsnippet

snippet for "For loop" !b
for (${3:size_t} ${2:i} = 0; $2 < ${1:count}; ++$2)
{
  ${VISUAL}$0
}
endsnippet

snippet fori "For loop over iterable" !b
for (const auto& ${1:item} : ${2:items})
{
  ${VISUAL}$0
}
endsnippet

snippet ar "Auto reference" !b
auto& ${1:variable} = $0
endsnippet

snippet car "Const auto reference" !b
const auto& ${1:variable} = $0
endsnippet

snippet try "Try-catch block" !b
try
{
  ${VISUAL}$0
}
catch (${1:std::runtime_error& e})
{
  // TODO: handle error
}
endsnippet

snippet fio "File IO" !b
#include <iostream>
#include <fstream>
std::ofstream file("filename.txt");
if (file.is_open())
{
  file << "Test";
  file.close();
}
endsnippet

snippet cout "std::cout output" !b
std::cout << ${1}${2: << std::endl};$0
endsnippet

#######################################################################
#                           Numeric limits                            #
#######################################################################

snippet nan "NaN" w
std::numeric_limits<${1:float}>::quiet_NaN()$0
endsnippet

snippet inf "Infinity" w
std::numeric_limits<${1:float}>::infinity()$0
endsnippet

snippet eps "Epsilon"
std::numeric_limits<${1:float}>::epsilon()$0
endsnippet

#######################################################################
#                              Includes                               #
#######################################################################

snippet inc "Include header" b
#include <${1:header.h}>$0
endsnippet

snippet incs "Include standard library header" b
#include <${1:iostream}>$0
endsnippet

snippet incl "Include local header" b
#include "${1:`!p snip.rv = snip.basename`}.${2:h}"$0
endsnippet

snippet incb "Include Boost library header" b
#include <boost/${1:format}.hpp>$0
endsnippet

snippet math "Include math header" !b
${1:#define _USE_MATH_DEFINES
}#include <cmath>$0
endsnippet

#######################################################################
#                           Random numbers                            #
#######################################################################

snippet random "Random (uniform int) number generator" !b
#include <random>
std::random_device rnd;
std::mt19937 gen(rnd());
std::uniform_int_distribution<> ${3:dist}(${1:0}, ${2});
$3(gen);
endsnippet

#######################################################################
#                           Variable types                            #
#######################################################################

snippet vec "Vector"
std::vector<${1:float}>$0
endsnippet

snippet str "String"
std::string$0
endsnippet

snippet csr "const String&" w
const std::string&$0
endsnippet

snippet map "Map" !
std::map<${1:size_t}, ${2:float}>$0
endsnippet

snippet inmap "Check if element is in map" !b
if (${1:map}.count (${2:element}) == 0)
{
  $0
}
endsnippet
